// Copyright 2023 Terramate GmbH
// SPDX-License-Identifier: MPL-2.0

package test

import (
	"path/filepath"
	"testing"

	"github.com/madlambda/spells/assert"
	"github.com/terramate-io/terramate/git"
)

const (
	// Username for the test commits.
	Username = "terramate tests"

	// Email for the test commits.
	Email = "terramate@mineiros.io"

	// DefBranch is the default repository branch.
	DefBranch = "main"
)

// NewGitWrapper tests the creation of a git wrapper and returns it if success.
// The env is the list of environment variables to be passed to git but if nil
// is provided then the complete os.Environ() is used.
func NewGitWrapper(t testing.TB, wd string, env []string) *git.Git {
	t.Helper()

	gw, err := git.WithConfig(git.Config{
		Username:       Username,
		Email:          Email,
		WorkingDir:     wd,
		Isolated:       true,
		Env:            env,
		AllowPorcelain: true,
	})
	assert.NoError(t, err, "new git wrapper")

	return gw
}

// EmptyRepo creates and initializes a git repository and checks for errors.
// If bare is provided, the repository is for revisions (ie: for pushs)
func EmptyRepo(t testing.TB, bare bool) string {
	t.Helper()

	gw := NewGitWrapper(t, "", []string{})

	repodir := TempDir(t)
	// resolve symlinks
	repodir, err := filepath.EvalSymlinks(repodir)
	assert.NoError(t, err, "evaluating symlinks")
	err = gw.Init(repodir, DefBranch, bare)
	assert.NoError(t, err, "git init")

	return repodir
}

// NewRepo creates and initializes a repository for terramate use cases. It
// initializes two repositories, one for working and other bare for the
// "remote". It sets up the working repository with a "origin" remote pointing
// to the local "bare" repository and push a initial main commit onto
// origin/main. The working git repository is returned and the other is
// automatically cleaned up when the test function finishes.
func NewRepo(t testing.TB) string {
	t.Helper()

	repoDir := EmptyRepo(t, false)
	remoteDir := EmptyRepo(t, true)

	gw := NewGitWrapper(t, repoDir, []string{})

	err := gw.RemoteAdd("origin", remoteDir)
	assert.NoError(t, err, "git remote add origin")

	path := WriteFile(t, repoDir, "README.md", "# generated by terramate tests")
	assert.NoError(t, gw.Add(path), "adding README.md to remote repo")
	assert.NoError(t, gw.Commit("add readme"))

	err = gw.Push("origin", "main")
	assert.NoError(t, err, "git push origin main")

	return repoDir
}
